/**
 * Generate code from /{{projectName}}-{{apis}}/src/main/java/{{packageName}}/config/BootSecurityConfig.java.hbs
 */
// @SkipOverwrite
package cn.ibizlab.config;

import cn.ibizlab.core.authentication.provider.LdapAuthenticationProvider;
import cn.ibizlab.core.authentication.provider.ServiceApiAuthenticationProvider;
import cn.ibizlab.util.security.SSOAuthenticationEntryPoint;
import cn.ibizlab.util.security.SSOAuthenticationFilter;
import cn.ibizlab.extensions.ey.EYTokenFilter;
import cn.ibizlab.util.security.AuthorizationTokenFilter;
import cn.ibizlab.util.security.GlobalSecurityConfig;
import cn.ibizlab.util.security.SM3PasswordEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class BootSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    AuthorizationTokenFilter authenticationTokenFilter;
    @Autowired
    EYTokenFilter eyTokenFilter;
    @Autowired
    GlobalSecurityConfig globalSecurityConfig;
    @Autowired
    ServiceApiAuthenticationProvider serviceApiProvider;
    @Autowired
    LdapAuthenticationProvider ldapProvider;
    @Autowired
    SSOAuthenticationFilter ssoAuthenticationFilter;
    @Autowired
    SSOAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(serviceApiProvider).authenticationProvider(ldapProvider).userDetailsService(userDetailsService);
    }

    @Bean
    GrantedAuthorityDefaults grantedAuthorityDefaults() {
        // Remove the ROLE_ prefix
        return new GrantedAuthorityDefaults("");
    }

    @Bean
    @ConditionalOnMissingBean(SM3PasswordEncoder.class)
    public PasswordEncoder passwordEncoderBean() {
        return NoOpPasswordEncoder.getInstance();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

               httpSecurity
                // 禁用 CSRF
                .csrf().disable()
                // 授权异常
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                // 不创建会话
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        //全局安全配置
        globalSecurityConfig.configure(httpSecurity);

        httpSecurity
                .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(ssoAuthenticationFilter,UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(eyTokenFilter, AuthorizationTokenFilter.class);
    }
}